package com.ferry.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;

public class  ImageUtils {

    private static final String[] types = ImageIO.getReaderFormatNames();

    private static String[] lowerTypes = null;


    /**
     * 获取图片指定缩略图
     * @param bytes
     * @param suffix
     * @param width
     * @param height
     * @return
     * @throws IOException
     */
    public static byte[] getThumbnailsImage(byte[] bytes, String suffix,int width,int height) throws IOException {
        if (isSupport(suffix)) {
            // 检测图片是否支持
            BufferedImage bi = getImage(bytes);
            int srcWidth = bi.getWidth();
            int srcHeight = bi.getHeight();

            Dimension computes = computes(width, height, srcWidth, srcHeight);
            BufferedImage draw = draw(bi, computes.width, computes.height);
            return getBytes(draw, suffix);
        } else {
            return null;
        }
    }


    /**
     * 给图片水印
     * @param bytes
     * @throws IOException
     */
    public static byte[] pressSign(byte[] bytes,String suffix,String text,Color color,Font font,int x,int y,float alpha) throws IOException{
        if (isSupport(suffix)) {
            // 确保字体可用
            String fontFamily = FontUtils.ensureFontFamilyName(font.getFontName());
            if (!fontFamily.equals(font.getFontName())) {
                font = new Font(fontFamily,font.getStyle(),font.getSize());
            }

            //开始绘制字体
            BufferedImage bi = getImage(bytes);
            int srcWidth = bi.getWidth();
            int srcHeight = bi.getHeight();
            Graphics2D graphics = bi.createGraphics();
            graphics.setComposite(AlphaComposite.getInstance(10,alpha));
            graphics.setColor(color);
            graphics.setFont(font);
            graphics.drawString(text,x,y);
            graphics.dispose();
            return getBytes(bi,suffix);
        } else {
            return null;
        }
    }

    /**
     * 绘制默认水印
     * @param bytes
     * @param suffix
     * @param text
     * @return
     * @throws IOException
     */
    public static byte[] pressSign(byte[] bytes,String suffix,String text,int size) throws IOException{
        BufferedImage image = getImage(bytes);
        int width = image.getWidth();
        int height = image.getHeight();
        return pressSign(bytes,suffix,text,Color.pink,
                new Font(FontUtils.getDefault(),Font.PLAIN,size),
                width - size * text.length() - size,height - size,0.8f);
    }

    /**
     * 检测图片格式是否能被支持
     * @param suffix
     * @return
     */
    public static boolean isSupport(String suffix) {
        String upper = suffix.toUpperCase(Locale.ROOT);
        for (String type : types) {
            if (upper.equals(type)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 绘制图片
     * @param image
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage draw(Image image,int width,int height) {
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = bi.getGraphics();
        graphics.drawImage(image,0,0,width,height,null);
        graphics.dispose();
        return bi;
    }

    /**
     * 计算图片尺寸
     * @param width
     * @param height
     * @param srcWidth
     * @param srcHeight
     * @return
     */
    public static Dimension computes(int width,int height,int srcWidth,int srcHeight) {
        if ((srcWidth*1.0)/width < (srcHeight*1.0)/height) {
            if (srcWidth > width) {
                height = Integer.parseInt(String.valueOf(srcHeight*width/(srcWidth*1.0)).replace(".0",""));
            }
        } else {
            if (srcHeight > height) {
                width = Integer.parseInt(String.valueOf(srcWidth*height/(srcHeight*1.0)).replace(".0",""));
            }
        }
        return new Dimension(width,height);
    }


    /**
     * 图片转byte数组
     * @param image
     * @param suffix
     * @return
     * @throws IOException
     */
    public static byte[] getBytes(BufferedImage image,String suffix) throws IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image,suffix,bos);
        return bos.toByteArray();
    }


    /**
     * byte数组转 图片
     * @param bytes
     * @return
     * @throws IOException
     */
    public static BufferedImage getImage(byte[] bytes) throws IOException{
        ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        return ImageIO.read(inputStream);
    }

    /**
     * 获取支持的图片后缀
     * @return
     */
    public static String[] getSupportTypes() {
        if (lowerTypes == null) {
            synchronized (ImageUtils.class) {
                lowerTypes = new String[types.length];
                for (int i = 0; i < types.length; i++) {
                    lowerTypes[i] = types[i].toLowerCase(Locale.ROOT);
                }
            }
        }
        return lowerTypes;
    }


    /**
     * 从文件读取
     * @param file
     * @return
     * @throws IOException
     */
    public static byte[] getImage(File file) throws IOException{
        if (file.exists()) {
            FileInputStream inputStream = new FileInputStream(file);
            return getImage(inputStream);
        } else {
            return null;
        }
    }

    /**
     * 从网络中获取图片
     * @param url
     * @return
     * @throws IOException
     */
    public static byte[] getImage(URL url) throws IOException{
        URLConnection urlConnection = url.openConnection();
        InputStream inputStream = urlConnection.getInputStream();
        if (inputStream != null) {
            return getImage(inputStream);
        } else {
            return null;
        }
    }

    /**
     * 从流中读取
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] getImage(InputStream inputStream) throws IOException{
        int len = 0;
        byte[] bytes = new byte[1024];
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        while ( (len = inputStream.read(bytes)) != -1) {
            outputStream.write(bytes,0,len);
        }
        return outputStream.toByteArray();
    }
}